package com.lmwyc.core;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lmwyc.bean.Card;
import com.lmwyc.bean.CardList;
import com.lmwyc.bean.UserSession;
import com.lmwyc.constant.Constant;
import com.lmwyc.util.HttpUtil;
import com.lmwyc.util.MailUtil;
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;
import com.twilio.type.PhoneNumber;

public class PunshThread implements Runnable {

	private static final Logger logger = LoggerFactory.getLogger(PunshThread.class);

	private UserSession user;
	private MailUtil mail;
	private String punshFailedTitle;
	private String punshFailedContent;
	
	public PunshThread(UserSession user, MailUtil mail, String punshFailedTitle, String punshFailedContent) {
		super();
		this.user = user;
		this.mail = mail;
		this.punshFailedTitle = punshFailedTitle;
		this.punshFailedContent = punshFailedContent;
	}

	@Override
	public void run() {
		int delay = user.getRandomDelay();
		delay = new Random().nextInt(delay);
		try {
			// 随机休眠一定时间
			Thread.sleep(delay * 60 * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 已打卡直接结束
		if (checkPunshed(user)) {
			logger.error(user.getUserName() + " 已打卡");
			mail.sendSimpleMail(user.getEmail(), "自动打卡", "检测到已打卡，无需自动打卡");
			return;
		}
		String result = getPunsh();
		logger.info("请求结果：" + result);
		if (result == null || "".equals(result) || '<' == result.charAt(0)) {
			logger.error(user.getUserName() + " 打卡失败");
			if(user.getPhone() != null && user.getPhone().trim().length() > 0) {
			    Twilio.init(Constant.ACCOUNT_SID, Constant.AUTH_TOKEN);
				PhoneNumber to = new PhoneNumber("+86" + user.getPhone());
				PhoneNumber from = new PhoneNumber(Constant.PHONE_FROM);
				Message message = Message.creator(to, from, punshFailedContent).create();
				logger.error(user.getUserName() + " 已发送短信 " + message.getSid());
			}else {
				mail.sendSimpleMail(user.getEmail(), punshFailedTitle, punshFailedContent);
			}
		} else {
			mail.sendSimpleMail(user.getEmail(), "自动打卡", "打卡成功");
		}
	}

	/**
	 * 判断是否已打卡
	 * 
	 * @param user
	 * @return
	 */
	public boolean checkPunshed(UserSession user) {
		Map<String, String> map = new HashMap<String, String>();
		Calendar c = Calendar.getInstance();
		map.put("year", c.get(Calendar.YEAR) + "");
		map.put("month", (c.get(Calendar.MONTH) + 1) + "");
		String res = HttpUtil.sendPost(Constant.GET_CARD_LIST, map, Constant.encoding, user.getUserSessionId());
		try {
			ObjectMapper mapper = new ObjectMapper();
			mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"));
			CardList cardList = mapper.readValue(res, CardList.class);
			List<Card> rows = cardList.getRows();
			// 没有记录
			if (rows == null || rows.size() < 1) {
				return false;
			}
			for (Card card : rows) {
				Calendar record_date = Calendar.getInstance();
				record_date.setTime(card.getRecord_date());
				// 获取当天的打卡记录
				if (record_date.get(Calendar.DAY_OF_MONTH) == c.get(Calendar.DAY_OF_MONTH)) {
					int currentTime = c.get(Calendar.HOUR_OF_DAY);
					// 判断当前时间是否上班打卡
					if (5 <= currentTime && 8 >= currentTime) {
						Date begin_time = card.getBegin_time();
						// 上班是否打卡
						if (begin_time != null) {
							Calendar temp = Calendar.getInstance();
							temp.setTime(begin_time);
							int begin_hour = temp.get(Calendar.HOUR_OF_DAY);
							// 上班打卡必须在5点到9点之间，必须做此判断，因为首次打卡时间在5点以前算作前一天的考勤
							if (5 <= begin_hour && 8 >= begin_hour) {
								return true;
							}
						}
					}

					// 判断当前时间是否下班打卡
					if (currentTime >= 18 || (currentTime >= 0 && currentTime < 5)) {
						Date last_update = card.getLast_update();
						// 下班是否打卡
						if (last_update != null) {
							Calendar temp = Calendar.getInstance();
							temp.setTime(last_update);
							int last_hour = temp.get(Calendar.HOUR_OF_DAY);
							// 下班打卡必须在18点到第二天5点之间，必须做此判断，因为末次打卡时间在18点以前算作早退
							if (last_hour >= 18 || (last_hour >= 0 && last_hour < 5)) {
								return true;
							}
						}
					}
					// 不满足以上任意条件
					return false;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(user.getUserName() + " 获取打卡记录失败");
		}
		return false;
	}

	/**
	 * 执行打卡
	 * 
	 * @param sessionId
	 * @return
	 */
	private String getPunsh() {
		Map<String, String> map = new HashMap<String, String>();
		Map<String, String> randomAxes = getRandomAxes(user.getLatitude(), user.getLongitude());
		map.put("latitude", randomAxes.get("latitude"));
		map.put("longitude", randomAxes.get("longitude"));
		map.put("ship_place_ind", "500");
		map.put("onwership_place", "北京");
		String url = "http://wkq.chinasoftosg.com/WeCard/card/punsh.do";
		return HttpUtil.sendPost(url, map, Constant.encoding, user.getUserSessionId());
	}

	/**
	 * 在指定地点附近生成随机坐标
	 * 
	 * @param lat
	 * @param lon
	 * @return
	 */
	private Map<String, String> getRandomAxes(double lat, double lon) {
		Random random = new Random();

		// 取值范围[-150, 150] ,即random.nextInt(150 - (-150) + 1) + (-150)
		int a = random.nextInt(301) - 150;
		int b = random.nextInt(301) - 150;

		Map<String, String> map = new HashMap<String, String>();
		// 差之毫厘谬以千里，只在千分位之后随机
		map.put("latitude", String.valueOf(String.format("%.5f", lat + a * 0.00001)));
		map.put("longitude", String.valueOf(String.format("%.5f", lon + b * 0.00001)));
		return map;
	}
}
